import 'package:rxdart/rxdart.dart';

import '../../common/test_page.dart';

class SequenceEqualsTestPage extends TestPage {
  SequenceEqualsTestPage(super.title) {
    test('Rx.sequenceEqual.equals', () async {
      final stream = Rx.sequenceEqual(Stream.fromIterable(const [1, 2, 3, 4, 5]),
          Stream.fromIterable(const [1, 2, 3, 4, 5]));

      expect(stream);
    });

    test('Rx.sequenceEqual.diffTime.equals', () async {
      final stream = Rx.sequenceEqual(
          Stream.periodic(const Duration(milliseconds: 100), (i) => i + 1)
              .take(5),
          Stream.fromIterable(const [1, 2, 3, 4, 5]));

      expect(stream);
    });

    test('Rx.sequenceEqual.equals.customCompare.equals', () async {
      final stream = Rx.sequenceEqual(Stream.fromIterable(const [1, 1, 1, 1, 1]),
          Stream.fromIterable(const [2, 2, 2, 2, 2]),
          equals: (int? a, int? b) => true);

      expect(stream);
    });

    test('Rx.sequenceEqual.diffTime.notEquals', () async {
      final stream = Rx.sequenceEqual(
          Stream.periodic(const Duration(milliseconds: 100), (i) => i + 1)
              .take(5),
          Stream.fromIterable(const [1, 1, 1, 1, 1]));

      expect(stream);
    });

    test('Rx.sequenceEqual.notEquals', () async {
      final stream = Rx.sequenceEqual(Stream.fromIterable(const [1, 2, 3, 4, 5]),
          Stream.fromIterable(const [1, 2, 3, 5, 4]));

      expect(stream);
    });

    test('Rx.sequenceEqual.equals.customCompare.notEquals', () async {
      final stream = Rx.sequenceEqual(Stream.fromIterable(const [1, 1, 1, 1, 1]),
          Stream.fromIterable(const [1, 1, 1, 1, 1]),
          equals: (int? a, int? b) => false);

      expect(stream);
    });

    test('Rx.sequenceEqual.notEquals.differentLength', () async {
      final stream = Rx.sequenceEqual(Stream.fromIterable(const [1, 2, 3, 4, 5]),
          Stream.fromIterable(const [1, 2, 3, 4, 5, 6]));

      expect(stream);
    });

    test('Rx.sequenceEqual.notEquals.differentLength.customCompare.notEquals',
            () async {
          final stream = Rx.sequenceEqual(Stream.fromIterable(const [1, 2, 3, 4, 5]),
              Stream.fromIterable(const [1, 2, 3, 4, 5, 6]),
              equals: (int? a, int? b) => true);

          // expect false,
          // even if the equals handler always returns true,
          // the emitted events length is different
          expect(stream);
        });

    test('Rx.sequenceEqual.equals.errors', () async {
      final stream = Rx.sequenceEqual(
        Stream<void>.error(ArgumentError('error A')),
        Stream<void>.error(ArgumentError('error A')),
        errorEquals: (e1, e2) => e1.error.toString() == e2.error.toString(),
      );

      expect(stream);
    });

    test('Rx.sequenceEqual.notEquals.errors', () async {
      final stream = Rx.sequenceEqual(
        Stream<void>.error(ArgumentError('error A')),
        Stream<void>.error(ArgumentError('error B')),
        errorEquals: (e1, e2) => e1.error.toString() == e2.error.toString(),
      );

      expect(stream);
    });

    test('Rx.sequenceEqual.single.subscription', () async {
      final stream = Rx.sequenceEqual(Stream.fromIterable(const [1, 2, 3, 4, 5]),
          Stream.fromIterable(const [1, 2, 3, 4, 5]));

      expect(stream);
      expect(() => stream.listen(null));
    });

    test('Rx.sequenceEqual.asBroadcastStream', () async {
      final future = Rx.sequenceEqual(Stream.fromIterable(const [1, 2, 3, 4, 5]),
          Stream.fromIterable(const [1, 2, 3, 4, 5]))
          .asBroadcastStream()
          .drain<void>();

      expect(future);
      expect(future);
    });
  }

}